package com.chu.cloud.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;

/**
 * 备注说明:拷贝对象属性, 可忽略值为空的属性
 * </p>
 */
public class BeanUtil extends PropertyUtils {
	/**
	 * 拷贝对象属性值,默认忽略null值的拷贝
	 * 
	 * @param dest 目标对象
	 * @param src 源对象
	 */
	public static void copyProperties(Object dest, Object src) {
		copyProperties(dest, src, true);
	}

	/**
	 * 
	 * @param dest 目标对象
	 * @param src 源对象
	 * @param isSkipNull 是否忽略为null值的属性拷贝
	 */
	public static void copyProperties(Object dest, Object src, boolean isSkipNull) {
		// Validate existence of the specified beans
		if (dest == null) {
			throw new IllegalArgumentException("No destination bean specified");
		}

		if (src == null) {
			throw new IllegalArgumentException("No origin bean specified");
		}
		// 获取所有src中的属性，存入于数组中
		PropertyDescriptor[] origDescriptors = PropertyUtils.getPropertyDescriptors(src);

		for (int i = 0; i < origDescriptors.length; i++) {
			// 取出src中属性名
			String name = origDescriptors[i].getName();

			if ("class".equals(name)) {
				continue; // No point in trying to set an object's class
			}

			if (PropertyUtils.isReadable(src, name) && PropertyUtils.isWriteable(dest, name)) {
				Object value = null;
				try {
					// 取出属性的值
					value = PropertyUtils.getSimpleProperty(src, name);
				} catch (Exception e) {
					throw new RuntimeException();
				}

				if (isSkipNull) {
					if (value == null) {
						continue;
					}
				} else if (value == null) {
					value = null;
				}

				try {
					setProperty(dest, name, value);
				} catch (Exception e) {
					throw new RuntimeException(BeanUtil.class.getSimpleName() + "copy error fiedName: name=" + name
							+ ",value=" + value + "\n" + e.getMessage());
				}
			}
		}
	}

	public static Map<String, Object> describe(final Object bean)
			throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
		Map<String, Object> map = PropertyUtils.describe(bean);
		if (map != null)
			map.remove("class");
		return map;
	}

	/**
	 * 将对象转换为map,并且删除class这个key
	 */
	public static Map<String, String> describeObject(Object obj) {
		return describeObject(obj, true);
	}

	/**
	 * 将对象转换为map
	 * 
	 * @param removeClassKey
	 *            是否删除class这个key,默认删除
	 */
	public static Map<String, String> describeObject(Object obj, Boolean removeClassKey) {
		try {
			Map<String, String> map = BeanUtils.describe(obj);
			if (removeClassKey == null || removeClassKey) {
				map.remove("class");
			}
			return map;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Map --> 利用org.apache.commons.beanutils 工具类实现 Map --> Bean
	 * 
	 * @param map
	 * @param obj
	 * @throws Exception
	 */
	public static void transMap2Bean(Map<String, Object> map, Object obj) throws Exception {
		BeanUtils.populate(obj, map);
	}
}
